/**
YASTACS main gui module.

License: GNU General Public License

YASTACS game
Copyright (C) 2012 Kalman Kiss, kiskami@freemail.hu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Contact author at: kiskami@freemail.hu or
Hungary, 8900 Zalaegerszeg
Kakukkfu u 4.
*/
module gui.Gui;

import std.stdio;

import ceguiint.CoreFuncs;
import ceguiint.WindowManager;
import ceguiint.SchemeManager;
import ceguiint.System;
import ceguiint.String;
import ceguiint.Window;
import ceguiint.ListboxItem;
import ceguiint.Combobox;

import ceguiint.SWIGTYPE_p_OIS__KeyEvent;
import ceguiint.SWIGTYPE_p_OIS__MouseEvent;
import ceguiint.SWIGTYPE_p_OIS__MouseButtonID;

import ogreint.RenderWindow; 

import iCore;

immutable string resgroup = "gui";
immutable string taharezlook_scheme = "TaharezLook.scheme";
immutable string taharezlook = "TaharezLook";
immutable string mousearrow = "MouseArrow";
immutable string root_window_name = "gui_root_wnd";

enum SubscriberEvents {
	PushButtonEventClicked
};

alias bool delegate(void *p) eventdelegate;

class Gui {

	// először
	void setCore(iCore core_) {
		core = core_;
	}

	static Gui instance() {
		synchronized {
			Gui tmp = s;
			if(!tmp) {
				tmp = s;
				if(!tmp) {
					tmp = new Gui();
					s = tmp;
				}
			}
			return s;
		}
	}

	void initialize() {
		auto ptr = RenderWindow.swigGetCPtr(core.rendersystem.renderwindow);
		//		debug writeln("Gui ctor: renderwindow ptr:", ptr);
		ceguicore = new CoreFuncs(ptr
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup)
								  , new String(resgroup));
		/*
		debug {
		writeln("CEGUI::System: ", System.getSingleton());
		writeln("CEGUI::WindowManager: ", WindowManager.getSingleton());
		writeln("CEGUI::SchemeManager: ", SchemeManager.getSingleton());
		}
		*/
		//		WindowManager winMgr = WindowManager.getSingleton();

		ceguicore.callbackFunc(&callbackfunc);

		ceguicore.showMouseCursor(false);

		// load scheme and set up defaults
		SchemeManager.getSingleton().create(new String(taharezlook_scheme)
											, new String(resgroup));
		System.getSingleton().setDefaultMouseCursor(new String(taharezlook)
													, new String(mousearrow));

		rootwindow = WindowManager.getSingleton().createWindow(new String("TaharezLook/StaticImage"), new String(root_window_name));
		core.gui.setProp(root_window_name,"Alpha","0");
		System.getSingleton().setGUISheet(rootwindow);
	}

/*
	private String createString(string s) {
		String s_ = new String();
		return s_.assign(s);
	}
*/

	Window loadLayout(string layout) {
		debug writeln("Gui loadLayout: ", layout);
	    return WindowManager.getSingleton().loadWindowLayout(new String(layout));
	}

	Window createWindow(string type, string name) {
		debug writeln("Gui create window: ", type, ":", name);
		return WindowManager.getSingleton().createWindow(new String(type), new String(name));
	}

	void add(Window w) {
		debug writeln("Gui add: ", w.getName().c_str());
//		if(asGuiSheet)
//			System.getSingleton().setGUISheet(w);
//		else
			System.getSingleton().getGUISheet().addChildWindow(w);
	}

	void remove(Window w, bool destroy=false) {
		debug writeln("Gui remove: ", w.getName().c_str());
		System.getSingleton().getGUISheet().removeChildWindow(w);
		if(destroy) WindowManager.getSingleton().destroyWindow(w);
	}

	Window getWindow(string windowname) {
		return WindowManager.getSingleton()
			.getWindow(new String(windowname));
	}

	string getProp(string windowname, string prop) {
		return getWindow(windowname)
			.getProperty(new String(prop)).c_str();
	}

	void setProp(string windowname, string prop, string value) {
		getWindow(windowname)
					.setProperty(new String(prop), new String(value));
	}

	 void windowResized(float newwidth, float newheight) {
		 ceguicore.windowResized(newwidth,newheight);
	 }

	 void mouseMoved(void *e) {
		 auto mme = new SWIGTYPE_p_OIS__MouseEvent(e,true);
		ceguicore.mouseMoved(mme);
	 }

	 void keyPressed(void *e) {
		 auto ke = new SWIGTYPE_p_OIS__KeyEvent(e,true);
		 ceguicore.keyPressed(ke);
	 }

	 void keyReleased(void *e) {
		 auto ke = new SWIGTYPE_p_OIS__KeyEvent(e,true);
		 ceguicore.keyReleased(ke);
	 }

	 void mousePressed(void *e, int buttonid) {
		 auto mme = new SWIGTYPE_p_OIS__MouseEvent(e,true);
		 auto mbtn = new SWIGTYPE_p_OIS__MouseButtonID(&buttonid,true);
		 ceguicore.mousePressed(mme,mbtn);
	 }

	 void mouseReleased(void *e, int buttonid) {
		 auto mme = new SWIGTYPE_p_OIS__MouseEvent(e,true);
		 auto mbtn = new SWIGTYPE_p_OIS__MouseButtonID(&buttonid,true);
		 ceguicore.mouseReleased(mme,mbtn);
	 }

	void Update(float timeSinceLastFrame) {
		ceguicore.timePulse(timeSinceLastFrame);
	}

	bool showMouseCursor(bool s=true) {
		return ceguicore.showMouseCursor(s);
	}

	void setWidgetText(string name, string text) {
		setProp(name,"Text",text);
	}

	string getWidgetText(string name) {
		return getProp(name, "Text");
	}

	void setWidgetEnabled(string name, bool e=true) {
		setProp(name,"Disabled",!e?"True":"False");
	}

	void subscribePushButtonEventClicked(string name, eventdelegate handler) {
		addEventSubscriber(name, SubscriberEvents.PushButtonEventClicked, handler);
	}

	bool guiEvent(int id, void *args) {
		if(id in subscribers) {
			return subscribers[id](args);
		} else {
			debug writeln("Gui.guiEvent: no such handler id: ", id);
		}
		return false;
	}

	void loadFont(string filename) {
		ceguicore.loadFont(new String(filename));
	}

	void loadImageSet(string filename) {
		ceguicore.loadImageSet(new String(filename));
	}

	void addToCombobox(string name, string item_text, uint item_id=0) {
		ceguicore.addListboxTextItemToCB(
										 new String(name)
										 , new String(item_text)
										 , item_id);
	}

	void comboboxSelectItem(string name, uint index, bool state=true) {
		auto cb = new Combobox(Window.swigGetCPtr(getWindow(name)),false);
		cb.setItemSelectState(index,state);
	}

	uint getComboboxSelectedItem(string name) {
		auto cb = new Combobox(Window.swigGetCPtr(getWindow(name)),false);
		ListboxItem i = cb.getSelectedItem();
		if(i !is null) return i.getID();
		return -1;
	}

private:
	static Gui s;

	CoreFuncs ceguicore;
	iCore core;

	Window rootwindow;

	int handlerid;
	eventdelegate[int] subscribers;

	bool addEventSubscriber(string name, SubscriberEvents event, eventdelegate handler) {

		subscribers[++handlerid] = handler;

		switch (event) {
			case SubscriberEvents.PushButtonEventClicked :
				ceguicore.subscribePushButtonEventClicked(new String(name),handlerid);
				break;
			default: break;
		}

		return true;
	}
}

extern (C++) bool callbackfunc(int id, void *args) {
	return Gui.instance().guiEvent(id, args);
}
